/** vlc插件
 * @file vlcwnd.cpp
 * @author Kiven Lee
 * @version 1.0
 * @date 2021-11-14
 *
 * @copyright Kivensoft (c) 2018 - 2021
 *
 */

#include "vlcwnd.hpp"
#include "klib/log.hpp"
#include "config.hpp"

using namespace miniplayer;

static const char* VLC_WND_CLASS = "VlcWndClass";

static const char *VLC_ARGS[] = {
    // "--repeat", // 循环播放当前项目
    "-I", "dummy", // 设置主界面模块
    // "--ignore-config", // 不会加载配置选项，也不会保存到配置文件，默认启用
    "--extraintf=logger",
    "--verbose=2",
    // "--demux=h264",
    // "--ipv4",
    // "--no-prefer-system-codecs",
    // "--rtsp-caching=300",
    "--network-caching=500",	//网络额外缓存值 (ms)
    // "--rtsp-frame-buffer-size=10000000",
    // "--rtsp-tcp",				//RTSP采用TCP传输方式
};

static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
    switch (message) {
        case WM_CHAR:
            switch (wParam) {
                case '0':
                    ::PostMessageA(Config::main_hwnd, WM_VLC_PLAYER, (WPARAM) PlayState::pause, 0);
                    break;
                case VK_ESCAPE:
                    ::PostMessageA(Config::main_hwnd, WM_VLC_PLAYER, (WPARAM) PlayState::stop, 0);
                    break;
            }
            break;

        case WM_CREATE:
            kwin::SetWindowUserData(hwnd, kwin::GetCreateParamFromLParam(lParam));
            break;

        default:
            return ::DefWindowProc(hwnd, message, wParam, lParam);
    }

    return 0;
}

miniplayer::VlcPlayer::VlcPlayer(): player(NULL), player_list(NULL),
        media(NULL), media_list(NULL), hwnd(NULL) {
    // 创建一个VLC实例
    if (Config::get_debug())
        inst = libvlc_new(sizeof(VLC_ARGS) / sizeof(VLC_ARGS[0]), VLC_ARGS);
    else
        inst = libvlc_new(0, NULL);
}

const char* miniplayer::VlcPlayer::play(const char* u8_path, bool repeat) {
    if (!inst) return "加载vlc播放器失败";

    stop();

    // 通过文件路径创建一个媒体实例,从路径中创建
    media = libvlc_media_new_path(inst, u8_path);
    if (media == NULL) return "加载媒体文件失败";

    return play2(repeat);
}

const char* miniplayer::VlcPlayer::play_url(const char* url, bool repeat) {
    if (!inst) return "加载vlc播放器失败";

    stop();

    // 通过文件路径创建一个媒体实例,从路径中创建
    media = libvlc_media_new_location(inst, url);
    if (media == NULL) return "加载媒体文件失败";

    return play2(repeat);
}

const char* miniplayer::VlcPlayer::play2(bool repeat) {
    if (repeat) {
        media_list = libvlc_media_list_new(inst);
        libvlc_media_list_add_media(media_list, media);
        player_list = libvlc_media_list_player_new(inst);
    }

    // 创建一个VLC播放器
    if (!player) {
        player = libvlc_media_player_new(inst);
        if (!player) return "创建vlc播放器失败";
        libvlc_video_set_key_input(player, false);

        if (repeat) {
            libvlc_media_list_player_set_media_player(player_list, player);
            libvlc_media_list_player_set_playback_mode(player_list, libvlc_playback_mode_loop);
        }

        // 因为是windows系统，所以需要设置一个HWND给播放器作为窗口,这里就直接使用桌面窗口,这里仅是测试
        if (create_window())
            libvlc_media_player_set_hwnd(player, hwnd);

        // libvlc_video_set_mouse_input(player, false);
        libvlc_video_set_key_input(player, false);
    }

    // 把打开的媒体文件设置给播放器
    if (repeat)
        libvlc_media_list_player_set_media_list(player_list, media_list);
    else
        libvlc_media_player_set_media(player, media);

    libvlc_media_release(media);
    media = NULL;

    // 开始播放视频
    if (repeat)
        libvlc_media_list_player_play(player_list);
    else
        libvlc_media_player_play(player);

    return nullptr;
}

bool miniplayer::VlcPlayer::create_window() {
    static bool is_register = false;
    if (!is_register) {
        is_register = true;

        WNDCLASSEX wcex = {
            .cbSize        = sizeof(WNDCLASSEX),
            .style         = CS_HREDRAW | CS_VREDRAW,     // 窗口样式
            .lpfnWndProc   = WndProc,                     // 窗口消息处理回调函数地址
            .cbClsExtra    = 0,
            .cbWndExtra    = 0,
            .hInstance     = Config::hinstance,
            .hIcon         = NULL,
            .hCursor       = LoadCursor(NULL, IDC_ARROW), // (HBRUSH)GetStockObject(LTGRAY_BRUSH),
            .hbrBackground = (HBRUSH) COLOR_BTNFACE,      //(COLOR_WINDOW + 1), // 窗口背景色
            .lpszMenuName  = NULL,                        // MAKEINTRESOURCE(IDC_WKEBROWSER), // 窗口菜单
            .lpszClassName = VLC_WND_CLASS,
            .hIconSm       = LoadIcon(NULL, IDI_APPLICATION)
        };

        if (!::RegisterClassExA(&wcex)) {
            Config::messagebox("应用程序必须运行在windows NT系统以上!", MB_ICONERROR);
            return false;
        }
    }

    hwnd = ::CreateWindowExA(0,
            VLC_WND_CLASS,     // widnow class
            NULL,              // window caption
            WS_POPUP,          // WS_OVERLAPPEDWINDOW, // window style
            0, 0, 0, 0,
            Config::main_hwnd, // parent window handle
            NULL,              // window menu handle
            Config::hinstance, // program instance handle
            this);             // creation parameters

    if (!hwnd) {
        Config::messagebox("创建窗口错误!", MB_ICONERROR);
        return false;
    }

    // 窗口置顶
    // ::SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE);

    ::ShowWindow(hwnd, SW_SHOWMAXIMIZED);
    ::UpdateWindow(hwnd);
    return true;
}

